﻿using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;

namespace Yyd.Security.ClientIp
{
    public class ClientIpCheckMiddleware : IMiddleware, ITransientDependency
    {
        private readonly ILogger<ClientIpCheckMiddleware> _logger;

        private readonly IClientIpCheck _clientIpCheck;

        private readonly ClientIpCheckOption _ipCheckOptions;

        public ClientIpCheckMiddleware(ILogger<ClientIpCheckMiddleware> logger, IClientIpCheck clientIpCheck,
            IOptions<ClientIpCheckOption> options)
        {
            _logger = logger;
            _clientIpCheck = clientIpCheck;
            _ipCheckOptions = options.Value;
        }

        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            var remoteIp = context.Connection.RemoteIpAddress;
            _logger.LogDebug("Request from Remote IP address: {RemoteIp}", remoteIp);

            if (remoteIp?.IsIPv4MappedToIPv6 ?? false)
            {
                remoteIp = remoteIp.MapToIPv4();
            }

            var ip = remoteIp?.ToString();

            // 任何一种包含在白名单中
            if (_ipCheckOptions.Whitelist.Contains(ip) || await _clientIpCheck.HasWhitelist(ip))
            {
                // 成功
                await next.Invoke(context);
                return;
            }

            _logger.LogWarning("Forbidden Request from Remote IP address: {RemoteIp}", remoteIp);
            context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
            await context.Response.WriteAsync($"Forbidden Request from Remote IP address: {remoteIp}");
        }
    }
}
